package com.student.work.service.impl;

import com.student.work.common.BaseResponse;
import com.student.work.common.ResultCodeEnum;
import com.student.work.mapper.*;
import com.student.work.model.*;
import com.student.work.service.JobService;
import com.student.work.utils.TimeUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;

/**
 * @date 2020/3/3 20:23
 */
@Service
public class JobServiceImpl implements JobService {

    private static final Logger log = LoggerFactory.getLogger(JobServiceImpl.class);

    @Autowired
    JobInfoMapper jobInfoMapper;

    @Autowired
    JobApplicationMapper jobApplicationMapper;

    @Autowired
    UserProfileMapper userProfileMapper;

    @Autowired
    UserAttendanceMapper attendanceMapper;

    @Autowired
    UserSalaryDetailMapper salaryDetailMapper;

    @Override
    public BaseResponse<Map<String, Object>> addJob(JobInfo jobInfo) {
        log.info("保存工作信息 --> 开始");
        Map<String, Object> result = new HashMap<>(16);
        Long publishUserId = jobInfo.getPublishUserId();
        if (publishUserId == null) {
            return BaseResponse.result(ResultCodeEnum.UN_LOGIN, result);
        }

        Long jobId = jobInfo.getJobId();
        Date date = new Date();
        jobInfo.setGmtModified(date);

        // 如果有jobId，更新数据；没有jobId，新增数据
        if (jobId == null) {
            jobId = System.currentTimeMillis();
            jobInfo.setJobId(jobId);
            jobInfo.setGmtCreate(date);
            jobInfoMapper.insert(jobInfo);
        } else {
            jobInfoMapper.update(jobInfo);
        }

        result.put("jobId", jobId);
        log.info("保存工作信息 --> 完成！jobId：" + jobId);
        return BaseResponse.result(ResultCodeEnum.SUCCESS, result);
    }

    @Override
    public BaseResponse<JobInfo> getJob(Long jobId) {
        log.info("获取工作详情 --> jobId：" + jobId);
        JobInfo jobInfo = jobInfoMapper.selectByJobId(jobId);
        return BaseResponse.result(ResultCodeEnum.SUCCESS, jobInfo);
    }

    @Override
    public BaseResponse<Map<String, Object>> getJobList(int pageNum, int pageSize, String jobKeyword, String departKeyword,
                                                        Integer isRecommend, Integer date, Long userId) {
        log.info("获取工作列表 --> 开始");
        Map<String, Object> result = new HashMap<>(16);
        if (pageNum == 0) {
            pageNum = 1;
        }
        if (pageSize == 0) {
            pageSize = 5;
        }
        result.put("pageNum", pageNum);
        result.put("pageSize", pageSize);

        pageNum = (pageNum - 1) * pageSize;

        // 工作标题搜索关键字
        if (StringUtils.isNotBlank(jobKeyword)) {
            jobKeyword = "'%" + jobKeyword + "%'";
        } else {
            jobKeyword = null;
        }

        // 部门搜索关键字
        if (StringUtils.isNotBlank(departKeyword)) {
            departKeyword = "'%" + departKeyword + "%'";
        } else {
            departKeyword = null;
        }

        // 时间段
        String startTime = null;
        if (date != null) {
            startTime = getTimeAgo(date);
            log.info("startTime --> " + startTime);
        }

        int total = jobInfoMapper.getCount(jobKeyword, departKeyword, isRecommend, startTime, userId);
        List<JobInfo> jobList = jobInfoMapper.getJobList(pageNum, pageSize, jobKeyword, departKeyword, isRecommend, startTime, userId);

        result.put("total", total);
        result.put("data", jobList);
        log.info("获取工作列表 --> 结束，总数：" + total);
        return BaseResponse.result(ResultCodeEnum.SUCCESS, result);
    }

    private String getTimeAgo(int date) {
        String startTime = null;
        long millis = System.currentTimeMillis();
        switch (date) {
            case 1:
                startTime = TimeUtils.oneHourAgo(millis);
                break;
            case 2:
                startTime = TimeUtils.twoFourHourAgo(millis);
                break;
            case 3:
                startTime = TimeUtils.sevenDayAgo(millis);
                break;
            case 4:
                startTime = TimeUtils.fourteenDayAgo(millis);
                break;
            case 5:
                startTime = TimeUtils.thirtyDayAgo(millis);
                break;
            default:
                startTime = null;
        }
        return startTime;
    }

    @Override
    public BaseResponse<Map<String, Object>> applyJob(JobApplication application) {
        log.info("申请工作 --> 开始");
        Map<String, Object> result = new HashMap<>(16);
        if (application.getApplyUserId() == null) {
            return BaseResponse.result(ResultCodeEnum.UN_LOGIN, null);
        }
        if (application.getJobId() == null) {
            return BaseResponse.result(ResultCodeEnum.EMPTY_JOB_ID, null);
        }

        long applyId = System.currentTimeMillis();
        application.setApplyId(applyId);
        Date date = new Date();
        application.setGmtCreate(date);
        application.setGmtModified(date);
        jobApplicationMapper.insert(application);

        result.put("applyId", applyId);
        log.info("申请工作 --> 结束，applyId：" + applyId);
        return BaseResponse.result(ResultCodeEnum.SUCCESS, result);
    }

    @Override
    public BaseResponse<Map<String, Object>> getListByUserId(int pageNum, int pageSize, Long userId, Integer applyStatus) {
        log.info("获取申请列表 --> 开始");
        Map<String, Object> result = new HashMap<>(16);
        if (pageNum == 0) {
            pageNum = 1;
        }
        if (pageSize == 0) {
            pageSize = 5;
        }
        result.put("pageNum", pageNum);
        result.put("pageSize", pageSize);

        pageNum = (pageNum - 1) * pageSize;

        int total = jobApplicationMapper.getCount(userId, applyStatus);
        result.put("total", total);

        List<JobApplication> applyList = jobApplicationMapper.getListByUserId(pageNum, pageSize, userId, applyStatus);
        if (CollectionUtils.isNotEmpty(applyList)) {
            // 根据jobId，查询具体的job信息
            Set<Long> jobIdList = new HashSet<>();
            for (JobApplication apply : applyList) {
                jobIdList.add(apply.getJobId());
            }
            List<JobInfo> jobList = jobInfoMapper.getJobByIdList(jobIdList);

            // 拼装数据
            List<Map<String, Object>> data = new ArrayList<>();
            for (JobApplication apply : applyList) {
                Map<String, Object> map = new HashMap<>(16);
                map.put("applyId", apply.getApplyId());
                map.put("applyUserId", apply.getApplyUserId());
                map.put("gmtCreate", TimeUtils.formatDate(apply.getGmtCreate()));
                map.put("gmtModified", TimeUtils.formatDate(apply.getGmtModified()));
                map.put("applyStatus", changeStatus(apply.getApplyStatus()));
                for (JobInfo job : jobList) {
                    if (job.getJobId().equals(apply.getJobId())) {
                        map.put("jobTitle", job.getJobTitle());
                        map.put("department", job.getDepartment());
                        map.put("jobId", job.getJobId());
                        map.put("publishUserId", job.getPublishUserId());
                    }
                }
                data.add(map);
            }
            result.put("data", data);
        }
        log.info("获取申请列表 --> 结束，总数：" + total);
        return BaseResponse.result(ResultCodeEnum.SUCCESS, result);
    }

    private String changeStatus(int applyStatus) {
        if (applyStatus == 1) {
            return "申请中";
        }
        if (applyStatus == 2) {
            return "通过";
        }
        if (applyStatus == 3) {
            return "拒绝";
        }
        return "申请中";
    }

    @Override
    public BaseResponse<Map<String, Object>> getApplyByUserId(int pageNum, int pageSize, Long userId, Integer applyStatus) {
        log.info("获取申请者列表 --> 开始");
        Map<String, Object> result = new HashMap<>(16);
        if (pageNum == 0) {
            pageNum = 1;
        }
        if (pageSize == 0) {
            pageSize = 5;
        }
        result.put("pageNum", pageNum);
        result.put("pageSize", pageSize);

        pageNum = (pageNum - 1) * pageSize;

        int total = jobInfoMapper.getApplyCount(userId, applyStatus);
        result.put("total", total);

        List<Map<String, Object>> applyList = jobInfoMapper.getApplyByUserId(pageNum, pageSize, userId, applyStatus);
        if (CollectionUtils.isNotEmpty(applyList)) {
            // 获取涉及的申请者的信息
            Set<Long> userIdList = new HashSet<>();
            for (Map<String, Object> map : applyList) {
                userIdList.add(Long.parseLong(map.get("applyUserId").toString()));
            }
            List<UserProfile> userList = userProfileMapper.getUserList(userIdList);

            // 拼装数据
            List<Map<String, Object>> data = new ArrayList<>();
            for (Map<String, Object> map : applyList) {
                Long applyUserId = Long.parseLong(map.get("applyUserId").toString());
                map.put("applyStatus", changeStatus(Integer.parseInt(map.get("applyStatus").toString())));
                map.put("gmtCreate", TimeUtils.formatDateStr(map.get("gmtCreate")));
                map.put("gmtModified", TimeUtils.formatDateStr(map.get("gmtModified")));
                for (UserProfile profile : userList) {
                    if (applyUserId.equals(profile.getUserId())) {
                        map.put("fullName", profile.getFullName());
                        map.put("gender", profile.getGender());
                        map.put("grade", profile.getGrade());
                        map.put("major", profile.getMajor());
                        map.put("phoneNumber", profile.getPhoneNumber());
                        map.put("profileId", profile.getProfileId());
                    }
                }
                data.add(map);
            }
            result.put("data", data);
        }
        log.info("获取申请者列表 --> 结束，总数：" + total);
        return BaseResponse.result(ResultCodeEnum.SUCCESS, result);
    }

    @Override
    public BaseResponse<Map<String, Object>> changeApply(JobApplication apply) {
        log.info("修改申请状态 --> 开始");
        Map<String, Object> result = new HashMap<>(16);
        Long applyId = apply.getApplyId();
        if (applyId == null) {
            return BaseResponse.result(ResultCodeEnum.LACK_PARAM, result);
        }
        apply.setGmtModified(new Date());
        jobApplicationMapper.update(apply);
        result.put("applyStatus", apply.getApplyStatus());
        log.info("修改申请状态 --> 完成");
        return BaseResponse.result(ResultCodeEnum.SUCCESS, result);
    }

    @Override
    public BaseResponse<Map<String, Object>> createAttendance(UserAttendance attendance, Integer type) {
        log.info("创建打卡记录 --> 开始，type：" + type);
        Map<String, Object> result = new HashMap<>(16);
        String nowDay = TimeUtils.getNowDay();
        attendance.setWorkDay(nowDay);
        Date date = new Date();
        attendance.setGmtModified(date);

        // 查询记录是否存在
        UserAttendance att = attendanceMapper.getAttendance(attendance);
        // type，1-上班，2-下班
        if (type == 1) {
            if (att != null) {
                return BaseResponse.result(ResultCodeEnum.HAS_ATTENDANCE, result);
            }
            long l = System.currentTimeMillis();
            attendance.setAttendanceId(l);
            attendance.setGmtCreate(date);
            attendance.setStartTime(date);
            attendanceMapper.insert(attendance);

            result.put("attendanceId", l);
        }
        if (type == 2) {
            if (att == null) {
                return BaseResponse.result(ResultCodeEnum.HAS_NOT_START, result);
            }
            attendance.setEndTime(date);
            attendance.setAttendanceId(att.getAttendanceId());
            attendanceMapper.update(attendance);
        }
        log.info("创建打卡记录 --> 完成");
        return BaseResponse.result(ResultCodeEnum.SUCCESS, result);
    }

    @Override
    public BaseResponse<Map<String, Object>> getAttendanceList(int pageNum, int pageSize, Long userId, Long jobId) {
        log.info("获取打卡记录列表 --> 开始");
        Map<String, Object> result = new HashMap<>(16);
        if (pageNum == 0) {
            pageNum = 1;
        }
        if (pageSize == 0) {
            pageSize = 5;
        }
        result.put("pageNum", pageNum);
        result.put("pageSize", pageSize);

        pageNum = (pageNum - 1) * pageSize;

        int total = attendanceMapper.getCount(userId, jobId);
        result.put("total", total);
        result.put("jobId", jobId);

        List<UserAttendance> list = attendanceMapper.getList(pageNum, pageSize, userId, jobId);
        result.put("data", list);
        log.info("获取打卡记录列表 --> 完成，总数：" + total);
        return BaseResponse.result(ResultCodeEnum.SUCCESS, result);
    }

    @Override
    public BaseResponse<Map<String, Object>> getSalaryList(int pageNum, int pageSize, Long userId, Long jobId) {
        log.info("获取薪资记录列表 --> 开始");
        Map<String, Object> result = new HashMap<>(16);
        if (pageNum == 0) {
            pageNum = 1;
        }
        if (pageSize == 0) {
            pageSize = 5;
        }
        result.put("pageNum", pageNum);
        result.put("pageSize", pageSize);

        pageNum = (pageNum - 1) * pageSize;

        int total = salaryDetailMapper.getCount(userId, jobId);
        result.put("total", total);
        result.put("jobId", jobId);

        List<UserSalaryDetail> list = salaryDetailMapper.getList(pageNum, pageSize, userId, jobId);
        result.put("data", list);
        log.info("获取薪资记录列表 --> 完成，总数：" + total);
        return BaseResponse.result(ResultCodeEnum.SUCCESS, result);
    }

    @Override
    public BaseResponse<Map<String, Object>> payOff(UserSalaryDetail detail) {
        log.info("发放薪资 --> 开始");
        Double salary = detail.getSalary();
        if(salary <= 0d){
            return BaseResponse.result(ResultCodeEnum.SUCCESS, null);
        }
        Map<String, Object> result = new HashMap<>(16);
        Date date = new Date();
        detail.setGmtCreate(date);
        detail.setGmtModified(date);
        long l = System.currentTimeMillis();
        detail.setDetailId(l);
        salaryDetailMapper.insert(detail);

        result.put("detailId", l);
        log.info("发放薪资 --> 完成");
        return BaseResponse.result(ResultCodeEnum.SUCCESS, result);
    }

    @Override
    public BaseResponse<Map<String, Object>> deleteJob(JobInfo job) {
        Map<String, Object> result = new HashMap<>(16);
        Long jobId = job.getJobId();
        if (jobId != null) {
            int delete = jobInfoMapper.delete(jobId);
            result.put("delete", delete);
        }
        return BaseResponse.result(ResultCodeEnum.SUCCESS, result);
    }

    @Override
    public BaseResponse<Map<String, Object>> getAttendance(Long jobId, Long studentId) {
        Map<String, Object> result = new HashMap<>(16);
        Date lastDate = salaryDetailMapper.getLastDate(studentId, jobId);
        Date date = new Date();

        if (lastDate != null) {
            result.put("last", TimeUtils.formatDate(lastDate));
        } else {
            lastDate = TimeUtils.getDateByString("2019-01-01 00:00:00");
            result.put("last", "无");
        }

        List<UserAttendance> attendances = attendanceMapper.getListByTime(lastDate, date);
        result.put("hour", 0.0);
        result.put("salary", 0.0);
        double hour = 0.0d;
        double salary = 0.0d;
        if (CollectionUtils.isNotEmpty(attendances)) {
            JobInfo jobInfo = jobInfoMapper.selectByJobId(jobId);
            Double hourlyWage = jobInfo.getHourlyWage();
            for (UserAttendance attendance : attendances) {
                Date startTime = attendance.getStartTime();
                Date endTime = attendance.getEndTime();
                if (endTime != null) {
                    double hours = TimeUtils.diffDate(startTime, endTime);
                    salary += hours * hourlyWage;
                    hour += hours;
                }
            }
            BigDecimal b = new BigDecimal(hour);
            result.put("hour", b.setScale(1, BigDecimal.ROUND_HALF_UP).doubleValue());
            b = new BigDecimal(salary);
            result.put("salary", b.setScale(1, BigDecimal.ROUND_HALF_UP).doubleValue());
        }
        return BaseResponse.result(ResultCodeEnum.SUCCESS, result);
    }
}
